package example;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * Semaphore通常用来控制同时访问特定资源的线程数量，通过协调各个线程以保证资源的合理应用
 *
 * 比如说停车场的例子，停车场的车位是有限的，同一时间内可以停的车的最大数量是一定的，
 * 当停车场停的车的数量满了的时候，这个时候如果又有车想要停的时候，必须等待停车场中的车离开车位才可以，接下来我们来模拟一下停车场的例子
 *
 * https://zhuanlan.zhihu.com/p/98593407
 *
 * @author DengZhiYuan
 * @version 1.0
 * @date 2023/3/11 19:07
 */
public class SemaphoreDemo {

    //常有的方法
//    acquire()：获取一个许可证，如果当前没有可用的许可证，则线程会进入等待状态，直到有可用的许可证。
//    acquire(int permits)：获取指定数量的许可证，如果当前可用的许可证数量不足，则线程会进入等待状态，直到有足够的许可证。
//    tryAcquire()：尝试获取一个许可证，如果当前没有可用的许可证，则返回 false，否则返回 true。
//    tryAcquire(int permits)：尝试获取指定数量的许可证，如果当前可用的许可证数量不足，则返回 false，否则返回 true。
//    release()：释放一个许可证，将当前许可证数量加 1。
//    release(int permits)：释放指定数量的许可证，将当前许可证数量加上指定数量。
//    availablePermits()：获取当前可用的许可证数量。
//    getQueueLength()：获取等待许可证的线程数量。
//    hasQueuedThreads()：判断是否有线程在等待许可证。
//    isFair()：判断是否为公平信号量，公平信号量按照线程请求许可证的顺序分配许可证，非公平信号量则不保证分配顺序。

    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        semaphoreDemo.demo1();
    }
    
    /**
     * 创建了一个 Semaphore 实例，并将其初始化为 5，表示同时只有 5 个线程可以访问共享资源。然后创建了 10 个 Worker 线程，
     *  它们会依次尝试获取许可证，如果已经达到了最大许可证数量，线程会进入等待状态，直到其他线程释放许可证。
     * @author DengZhiYuan
     * @version 1.0
     * @date 2023/3/11 19:36
     * @param 
     * @return 
     */
    public void demo1(){
        Semaphore semaphore = new Semaphore(3);
        int n = 10;
        for (int i = 0; i < n; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println("开始："+Thread.currentThread().getName());
                    TimeUnit.SECONDS.sleep(5);
                    System.out.println("结束："+Thread.currentThread().getName());
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }

            }, "线程"+i+"开始").start();

        }

    }



}
